# 定义类
class Car:
    def __init__(self,wheelNum,colour):
        self.wheelNum  = wheelNum
        self.colour = colour              # 构造方法

# 方法
    def run(self):
      print('{}个轮子的{}车在行驶中....'.format(self.wheelNum,self.colour))

BMW = Car(4,'红色')      # 创建对象
Audi =Car(4,'white')     # 创建对象
BMW.run()                                # d调用方法
Audi.run()                                # 调用方法

# 定义学生类
class Student:
    def __init__(self, num, name, credit, course):  # 构造方法定义学生的属性
        self.num = num
        self.name = name
        self.credit = credit
        self.course = course

    def choose(self, c):  # 定义学生选课方法
        self.credit += c.credit
        self.course.append(c.name)

# 定义课程类
class Cou:
    def __init__(self, num, name, credit):  # 构造方法定义课程属性
        self.num = num
        self.name = name
        self.credit = credit

stu_1 = Student('201801', 'jack', 0, [])  # 创建学生——1
stu_2 = Student('201802', 'tom', 3, ['math'])  # 创建学生——2
cou_1 = Cou('01', 'Python', 3)  # 创建 课程1
cou_2 = Cou('02', 'C', 4)  # 创建 课程2 (changed from '4' to 4)
stu_1.choose(cou_1)  # 调用方法实现学生1 选课程1
stu_2.choose(cou_2)  # 调用方法实现学生2 选课程2
# 输出各学生的信息
print('学号:', stu_1.num, '姓名:', stu_1.name, '总学分:', stu_1.credit, '所选课程:', stu_1.course)
print('学号:', stu_2.num, '姓名:', stu_2.name, '总学分:', stu_2.credit, '所选课程:', stu_2.course)


# 数据封装
class Student(object):
    def __init__(self,name,score):
        self.name=name
        self.score=score

    def get_grade(self):
        if self.score >=90:
            return 'A'
        elif self.score >=60:
            return 'B'
        else:
            return 'c'
lisa = Student('lisa',99)
bart = Student('Bart',59)
print(lisa.name,lisa.get_grade())
print(bart.name,bart.get_grade())

# 析构方法
class Animal():
    def __init__(self):               # 构造方法
        print('--构造方法被调用--')
    # 析构方法
    def __del__(self):
        print('----析构方法被调用----')

# 创建对象

dog = Animal()
del dog
print(
    '------程序结束------'
)

# 定义类
class Car:
    price = 150000      # 类成员
    def __init__(self,colour):
        self.colour =  colour  # 实例成员
car_1  = Car('红色')    # 创建对象
print(car_1.price,Car.price,car_1.colour)    # 访问类成员和实例成员并输出
Car.name = 'Judi' # 增加类成员
car_1.wheel_Num = 4  # 增加实例成员
print(car_1.wheel_Num,car_1.name,Car.name)    # 访问类成员和实例成员并输出

# 定义类
class Car:
    price = 5000     # 类成员
    def __init__(self):
        self.price = 100000  # 实例成员
car_1 = Car()        # 创建对象
print(car_1.price,Car.price)    # 访问类成员和实例成员并输出

#  封装
"""
class A:      # 定义类
    def __init__(self):
        self.__X = 10 # 定义私有变量并赋值

    def __foo(self):
        print('from A') # 定义私有方法
a = A()   # 创建对象
print(a.__X)    # 输出私有变量值
a.__f00()        # 调用私有方法
"""

class A :     # 定义类
    def __init__(self):
        self.__X = 10     # 定义私有变量并赋值
    def __foo(self):   # 定义私有方法
        print('from A')
    def bar(self):      # 定义私有方法
        print('from A')
    def bar(self):      # 定义接口函数
        self.__foo()     # 类的内部访问私有方法
        return self.__X    # 返回私有变量__X的值
a  =A()     # 创建对象
b =a.bar()    # 调用接口函数，将返回值赋给b
print(b)      # 输出b的值

# 继承

# 定义一个父类
class Person:
    name = '人'
    age = 30
    def speak(self):
        print('%s 说:我 %d 岁.'% (self.name,self.age))
    # 定义一个子类:
class Stu(Person):
    def set_name(self,new_name):
        self.name=new_name
    def s_speak(self):
        print('%s 说:我 %d 岁 .'%(self.name,self.age))
student = Stu()        # 创建学生的对象
print('student的名字为:',student.name)     # 输出学生的姓名
print('student的年龄为:',student.age)      # 输出学生的年龄
student.s_speak()
student.set_name('jack')         # 调用子类的方法修改名字
student.speak()          # 调用父类方法用于输出

# 多继承
#  定义沙发父类
class Sofa:
    def print_a(self):
        print('----这是沙发')
# 定义床父类
class Bed:
    def print_b(self):
        print('----这是床----')
# 定义一个子类，继承自sofa 和 bed
class Sofa_bed(Sofa,Bed):
    def print_c(self):
        print('-----这是沙发床-----')
obj_C = Sofa_bed()  # 创建对象
obj_C.print_a()     # 调用Sofa父类的方法
obj_C.print_c()     # 调用自身的方法

# 统计学生人数

class Student:
    count = 0   # 类属性，用于统计人数

    def __init__(self,name):
        self.name=name        # 创建实例
        Student.count +=1     # 每次创建实例，类属性count加1

# 测试代码
stu_1  = Student('Alice')
stu_2  = Student('jack')
stu_3  = Student('Mike')

print(Student.count)

#   重写父类并调用
#   定义一个父类
class Person:
    def speak(self):           # 定义方法用于输出
        print('我是一个人类')
# 定义一个子类
class Stu(Person):
    def speak(self):
        print('我是一个学生')
student = Stu()       # 创建学生的对象
student.speak()       # 调用同名方法

# 定义父类
class Person:
    def __init__(self,name,sex):
        self.name = name
        self.sex = sex
# 定义子类
class Stu(Person):
    def __init__(self,name,sex,score):
        super().__init__(name,sex)    # 调用父类中的__init__方法
        self.score=score
# 创建对象的实例
student = Stu('jack','male',90)
print('姓名:%s,性别:%s,成绩:%s'%(student.name,student.sex,student.score))

#  多态
# 定义父类
class Person:
    def __init__(self,name,gender):
        self.name = name
        self.gender = gender
    def who(self):           # 定义 who 方法
        print('i am a Person ,my name is %s '%self.name)

# 定义学生子类:
class Student(Person):
    def __init__(self,name,gender,score):
        super().__init__(name,gender)    # 调用父类方法
        self.score=score
    def who(self):
        print('i am a Student,my name is %s '%self.name)   # 重写父类方法

# 定义教师子类
class Teacher(Person):
    def __init__(self,name,gender,course):
        super().__init__(name,gender)
        self.course = course
    def who(self):       # 重写父类方法
        print('i am a teacher,my name is %s' %self.name)
# 定义函数用于接收对象
def fun(x):
    x.who()     # 调用 who 方法

# 创建对象

P = Person('Jack','Male')
S = Student('Tom','Male',88)
t = Teacher('Lily','Female','English')

# 调用函数
fun(P)
fun(S)
fun(t)

# 类方法
class People:
    country = 'china'   # 定义类成员并赋值
# 类方法，用class method来进行修饰
    @classmethod
    def get_country(cls):
        return cls.country    # 返回类成员的值
p = People()         # 创建对象
print(p.get_country())    # 通过实例名调用
print(People.get_country())    # 通过类名调用
"""

# 静态方法   static
# 定义类
class Test:           # 静态方法，用 @staticmethod 进行修饰
    def s_print(self):
        print('-----静态方法-----')
t = Test()       # 创建对象
Test.s_print()   #通过类名调用
t.s_print()      # 通过对象名调用
"""
# 猫狗大战
# 定义一个猫类
class Cat:
    role = 'cat'   # 猫的角色属性都是猫
# 构造方法初始化猫
    def __init__(self,name,breed,aggressivity,life_value):
        self.name=name       # 每只猫都有自己的昵称
        self.breed=breed     # 每只猫都有自己的品种
        self.aggrressivity = aggressivity  # 每只猫都有自己的攻击力
        self.life_value = life_value   # 每只猫都有自己的生命值
# 定义猫攻击狗的方法:
    def attack(self,dog):
        dog.life_value -= self.aggrressivity  # 狗的生命值会根据猫的攻击力而下降
# 定义增长生命值的方法
    def attack(self,dog):
        dog.life_value +=50
# 判断是否死亡的方法
    def die(self):
        if self.life_value <=0:     # 如果生命值小于或等于0表示被对方击败
            print(self.name,'已被击败!')
        else:
            print(self.name,'的生命值还有',self.life_value)
# 定义一个狗类
class Dog:
    role = 'dog'     # 狗的角色属性都是狗
# 构造方法初始化狗
def __init__(self,name,breed,aggressivity,life_value):
    self.name = name       # 每只狗都有自己的昵称
    self.breed = breed     # 每一只狗都有自己的品种
    self.aggressivity = aggressivity   # 每只狗都有自己的攻击力
    self.life_value = life_value    # 每只狗都有自己的生命值
# 定义狗攻击猫的方法
def bite(self,cat):
    cat.life_value -=self.aggressivity  # 猫的生命值会根据狗的攻击力下降
# 定义增长生命值的方法
def die(self):
    self.life_value+=30
# 定义判断是否死亡的方法
def die(self):
    if self.life_value<=0:
        print('被击败')
    else:
        print(self.name,'的生命值还有',self.life_value)
# 创建实例
cat_1 = Cat('Mily','波斯猫',30,1500)  # 创造了实实在在的猫
dog_1 = Dog('Lucky','哈士奇', 50)   # 创造了一只实实在在的狗
cat_1.die()      # 输出猫的当前状态
dog_1.die()      # 输出狗的当前状态
print('-----开始战斗-----')
cat_1.attack(dog_1)     # 猫攻击狗一次
dog_1.bite(cat_1)       # 狗攻击猫一次
cat_1.die()             # 输出猫的输出状态
dog_1.die()             # 输出狗的输出状态
for i in range(29):     # 循环实现，猫攻击狗28次
    cat_1.attack(dog_1)
dog_1.die()      # 输出狗的当前状态
cat_1.eat()      # 猫吃东西一次
cat_1.die()      # 输出猫的当前状态
